/**
 * Copyright 2004 - 2007 Blue Bamboo International Inc. 
 *           All rights reserved.
 *
 *
 * Blue Bamboo PROPRIETARY/CONFIDENTIAL.
 *
 */

package com.bambamboo.socket.server.netty;

import java.net.InetSocketAddress;
import java.util.Map;
import java.util.concurrent.Executors;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import com.bambamboo.socket.server.ServerConfigurationBean;
import com.bambamboo.socket.server.Server;

/**
 * @author Nick.Tan
 * @deprecated use {@link NettyTCPServer}
 * @see {@link Server}
 */
public class NettyServer {

	private static Log logger = LogFactory.getLog(NettyServer.class);
	private ApplicationContext appCtx;

	public static void main(String[] args) throws Exception {
		NettyServer app = new NettyServer();
		app.initialize(args);
		app.startup();
	}

	private void initialize(String[] args) {
		appCtx = new FileSystemXmlApplicationContext("./config/applicationContext-netty.xml");
	}

	@SuppressWarnings("unchecked")
	private void startup() throws Exception {
		Map<String, ServerConfigurationBean> beans = appCtx.getBeansOfType(ServerConfigurationBean.class);
		logger.info("===== starting app... =====");
		for (Map.Entry<String, ServerConfigurationBean> entry : beans.entrySet()) {
			ServerConfigurationBean bean = entry.getValue();
			if (bean.isEnable() == false) {
				logger.info("server configuration disabled: " + bean);
				continue;
			}

			ChannelFactory factory = new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors
					.newCachedThreadPool());

			ServerBootstrap bootstrap = new ServerBootstrap(factory);
			ChannelPipeline pipeline = bootstrap.getPipeline();
			Class channelHandlerClazz = Class.forName(bean.getHandler());
			BaseChannelHandler channelHandler = (BaseChannelHandler) channelHandlerClazz.newInstance();
			channelHandler.setConfigurationBean(bean);
			pipeline.addLast(channelHandlerClazz.getName(), channelHandler);
			String port = bean.getPort();
			try {
				bootstrap.bind(new InetSocketAddress(Integer.parseInt(port)));
				logger.info(String.format(">>> listening on port [%s]", port));
			}
			catch (Exception e) {
				// catch to continue binding other ports
				logger.error(String.format(">>> binding on port [%s] failure!", port), e);
			}
		}

		logger.info("===== app started =====");
	}
}
